package handlers

import (
	"sysu-giep/internal/api/middleware"
	"sysu-giep/internal/database/models"
	"sysu-giep/internal/service"
	"sysu-giep/pkg/auth"
	"sysu-giep/pkg/logger"
	"sysu-giep/pkg/response"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// RegisterRequest 注册请求
type RegisterRequest struct {
	Username         string   `json:"username" binding:"required,min=3,max=50"`
	Email            string   `json:"email" binding:"required,email"`
	Password         string   `json:"password" binding:"required,min=6"`
	RealName         string   `json:"real_name" binding:"required"`
	Role             string   `json:"role" binding:"required,oneof=enterprise tutor student"`
	Phone            string   `json:"phone"`
	Organization     string   `json:"organization,omitempty"`     // 企业名称
	Department       string   `json:"department,omitempty"`      // 所属学院
	ResearchDirection []string `json:"research_direction,omitempty"` // 研究方向
}

// LoginRequest 登录请求
type LoginRequest struct {
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required"`
}

// RefreshTokenRequest 刷新令牌请求
type RefreshTokenRequest struct {
	RefreshToken string `json:"refresh_token" binding:"required"`
}

// Register 用户注册
// @Summary 用户注册
// @Description 用户注册接口，注册后账户自动激活，无需管理员审核
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body RegisterRequest true "注册信息"
// @Success 200 {object} response.Response{data=map[string]interface{}}
// @Failure 400 {object} response.Response
// @Router /auth/register [post]
func Register(c *gin.Context) {
	var req RegisterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	// 创建用户服务
	userService := service.NewUserService()

	// 创建用户模型
	user := &models.User{
		Username: req.Username,
		Email:    req.Email,
		Password: req.Password,
		RealName: req.RealName,
		Role:     models.UserRole(req.Role),
		Phone:    req.Phone,
		Status:   models.StatusApproved, // 直接设置为已通过状态，取消管理员审核
	}

	// 准备额外字段数据
	var extraData map[string]interface{}
	if req.Role == "enterprise" && req.Organization != "" {
		extraData = map[string]interface{}{
			"organization": req.Organization,
		}
	} else if (req.Role == "tutor" || req.Role == "student") && req.Department != "" {
		extraData = map[string]interface{}{
			"department":        req.Department,
			"research_direction": req.ResearchDirection,
		}
	}

	// 创建用户
	if err := userService.CreateUserWithExtraData(user, extraData); err != nil {
		logger.ErrorLog("用户注册失败", logger.Error(err))
		response.BadRequest(c, err.Error())
		return
	}

	response.SuccessWithMessage(c, "注册成功，账户已激活", gin.H{
		"username": req.Username,
		"email":    req.Email,
		"role":     req.Role,
		"status":   "approved",
	})
}

// Login 用户登录
// @Summary 用户登录
// @Description 用户登录接口
// @Tags 认证
// @Accept json
// @Produce json
// @Param request body LoginRequest true "登录信息"
// @Success 200 {object} response.Response{data=map[string]interface{}}
// @Failure 400 {object} response.Response
// @Router /auth/login [post]
func Login(c *gin.Context) {
	var req LoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	// 创建用户服务
	userService := service.NewUserService()

	// 根据邮箱获取用户
	user, err := userService.GetUserByEmail(req.Email)
	if err != nil {
		logger.ErrorLog("用户登录失败", logger.Error(err))
		response.BadRequest(c, "邮箱或密码错误")
		return
	}

	// 验证密码
	if !auth.CheckPassword(req.Password, user.Password) {
		logger.ErrorLog("用户登录失败", logger.String("email", req.Email), logger.String("reason", "密码错误"))
		response.BadRequest(c, "邮箱或密码错误")
		return
	}

	// 检查用户状态
	if user.Status != models.StatusApproved {
		response.BadRequest(c, "账户状态异常，请联系管理员")
		return
	}

	// 生成JWT令牌（使用全局实例）
	token, err := middleware.JWTManager.GenerateToken(user)
	if err != nil {
		logger.ErrorLog("生成JWT令牌失败", logger.Error(err))
		response.InternalServerError(c, "登录失败，请稍后重试")
		return
	}

	// 生成刷新令牌
	refreshToken, err := middleware.JWTManager.GenerateRefreshToken(user)
	if err != nil {
		logger.ErrorLog("生成刷新令牌失败", logger.Error(err))
		response.InternalServerError(c, "登录失败，请稍后重试")
		return
	}

	response.Success(c, gin.H{
		"token":         token,
		"refresh_token": refreshToken,
		"user": gin.H{
			"id":        user.ID,
			"username":  user.Username,
			"email":     user.Email,
			"role":      user.Role,
			"real_name": user.RealName,
			"status":    user.Status,
		},
	})
}

// RefreshToken 刷新令牌
// @Summary 刷新令牌
// @Description 刷新JWT令牌
// @Tags 认证
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.Response{data=map[string]interface{}}
// @Failure 401 {object} response.Response
// @Router /auth/refresh [post]
func RefreshToken(c *gin.Context) {
	var req RefreshTokenRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	// 验证刷新令牌（使用全局实例）
	claims, err := middleware.JWTManager.ValidateToken(req.RefreshToken)
	if err != nil {
		logger.ErrorLog("刷新令牌验证失败", logger.Error(err))
		response.Unauthorized(c, "刷新令牌无效")
		return
	}

	// 获取用户信息
	userService := service.NewUserService()
	user, err := userService.GetUserByID(claims.UserID)
	if err != nil {
		logger.ErrorLog("获取用户信息失败", logger.Error(err))
		response.Unauthorized(c, "用户不存在")
		return
	}

	// 检查用户状态
	if user.Status != models.StatusApproved {
		response.BadRequest(c, "账户状态异常，请联系管理员")
		return
	}

	// 生成新的访问令牌
	newToken, err := middleware.JWTManager.GenerateToken(user)
	if err != nil {
		logger.ErrorLog("生成新令牌失败", logger.Error(err))
		response.InternalServerError(c, "刷新令牌失败，请稍后重试")
		return
	}

	// 生成新的刷新令牌
	newRefreshToken, err := middleware.JWTManager.GenerateRefreshToken(user)
	if err != nil {
		logger.ErrorLog("生成新刷新令牌失败", logger.Error(err))
		response.InternalServerError(c, "刷新令牌失败，请稍后重试")
		return
	}

	logger.Info("令牌刷新成功", logger.String("username", user.Username))

	response.Success(c, gin.H{
		"token":         newToken,
		"refresh_token": newRefreshToken,
	})
}

// Logout 用户登出
// @Summary 用户登出
// @Description 用户登出接口
// @Tags 认证
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.Response
// @Router /auth/logout [post]
func Logout(c *gin.Context) {
	// 获取当前用户ID
	userID := c.GetUint("user_id")
	username := c.GetString("username")

	// 这里可以实现令牌黑名单等逻辑
	// 目前只是简单的响应成功

	logger.Info("用户登出", logger.String("username", username), zap.Uint64("user_id", uint64(userID)))

	response.SuccessWithMessage(c, "登出成功", nil)
}
